<script setup>
import { ref, onMounted } from 'vue'
import { sessionApi, listMenusApi, treeMenusApi, sortMenuApi, saveMenuApi, oneMenuApi, delMenusApi } from '@/commons/api'
import routes from '@/commons/router'
import TreeSel from '@/components/cascader/TreeSel'
import { CScrollbar } from 'c-scrollbar'
import Loader from '@/components/loader/Loader'
import Msg from '@/components/message'
import Confirm from '@/components/confirm'
import SvgIcon from '@/components/svgicon/SvgIcon'

// 定义是否显示加载的变量
const loadShow = ref(false)

// 界面挂载前处理
onMounted(() => {
  // 获取用户会话信息
  checkAuth()
})

let myAuth = {
  saveAuth: false,
  procAuth: false
}
// checkAuth 获取权限
const checkAuth = async () => {
  loadShow.value = true
  try {
    const res = await sessionApi()
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      const userBtnCode = res.data.btnCodes
      myAuth = {
        saveAuth: userBtnCode.indexOf('1001010201') !== -1,
        procAuth: userBtnCode.indexOf('1001010202') !== -1
      }
      await list()
    } else {
      localStorage.removeItem("token")
      Msg({ kind: 'error', txt: res.msg })
      routes.replace('/login')
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

const menuList = ref([])
const hasData = ref(false)
// list 列表展示
const list = async () => {
  hasData.value = false
  const res = await listMenusApi()
  if(res.code === import.meta.env.VITE_SUCCESS_CODE && res.data) {
    hasData.value = true
    menuList.value = res.data
    idList.value = []
    checkList.value = []
    allCheck.value = false
    res.data.forEach(() => {
      checkList.value.push(false)
    })
  }
}

// 选择效果实现
const idList = ref([])
const checkList = ref([])
const allCheck = ref(false)
// checkAll 全选
const checkAll = () => {
  idList.value = []
  checkList.value = []
  allCheck.value = !allCheck.value
  if(allCheck.value) {
    menuList.value.forEach(item => {
      idList.value.push(item.menuId)
      checkList.value.push(true)
    })
  } else {
    menuList.value.forEach(() => {
      checkList.value.push(false)
    })
  }
}
// checkCurId 单选
const checkCurId = (idx, menuId) => {
  if(!checkList.value[idx]) {
    idList.value.push(menuId)
  } else {
    idList.value.splice(idList.value.findIndex(id => id === menuId), 1)
  }
  checkList.value[idx] = !checkList.value[idx]
}

const menuForm = ref({
  menuId: '',
  menuName: '',
  menuCode: '',
  parentId: '',
  parentName: '',
  parentCode: '',
  sort: 0,
  icon: '',
  url: '',
  showed: 1,
  remarks: ''
})
// add 新增
const showModal = ref(false)
const add = () => {
  showModal.value = true
  treeMenus()
}

// 获取菜单数
const treeRef = ref([])
const treeMenus = async () => {
  const res = await treeMenusApi()
  if(res.code === import.meta.env.VITE_SUCCESS_CODE && res.data) {
    treeRef.value = res.data
    treeRef.value.unshift({
      selId: '111111111111111111111',
      selName: '一级菜单',
      selCode: '10000000',
      parentId: '000000000000000000000',
      children: null
    })
  } else {
    treeRef.value.push({
      selId: '111111111111111111111',
      selName: '一级菜单',
      selCode: '10000000',
      parentId: '000000000000000000000',
      children: null
    })
  }
}

// update 修改
const update = async (menuId) => {
  const res = await oneMenuApi({ menuId })
  if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
    showModal.value = true
    menuForm.value = res.data
    await treeMenus()
  } else {
    Msg({ kind: 'info', txt: '暂无内容' })
  }
}
// save 保存提交
const save = async () => {
  let menuId = menuForm.value.menuId
  let menuName = menuForm.value.menuName
  let menuCode = menuForm.value.menuCode
  let parentId = menuForm.value.parentId
  let sort = parseInt(menuForm.value.sort)
  menuForm.value.sort = sort
  if(menuName === '' || menuName.length > 50) {
    Msg({ kind: 'warn', txt: '菜单的名称不能为空，且长度不超过50个字符' })
    return
  } else if(menuCode === '' || menuCode.length !== 8) {
    Msg({ kind: 'warn', txt: '菜单的编码不能为空，且长度为8位的数字编码' })
    return
  } else if(parentId === '' || parentId.length !== 21) {
    Msg({ kind: 'warn', txt: '父级菜单不能为空' })
    return
  } else if(sort < 1) {
    Msg({ kind: 'warn', txt: '菜单排序不能为空' })
    return
  } else if(menuId === parentId) {
    Msg({ kind: 'warn', txt: '不可选择当前菜单为父级菜单' })
    return
  }
  loadShow.value = true
  try {
    const res = await saveMenuApi(menuForm.value)
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      closeModal()
      await list()
      Msg({ kind: 'success', txt: '恭喜您，菜单信息保存成功！' })
    } else {
      Msg({ kind: 'error', txt: res.msg })
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

// closeModal 关闭弹出层，并重置表单数据
const closeModal = () => {
  showModal.value = false
  menuForm.value = {
    menuId: '',
    menuName: '',
    menuCode: '',
    parentId: '',
    parentName: '',
    parentCode: '',
    sort: 0,
    icon: '',
    url: '',
    showed: 1,
  }
}

// deletes 批量删除菜单
const deletes = async() => {
  if(!idList || idList.value.length===0) {
    Msg({ kind: 'warn', txt: '请至少选择一项再操作！' })
    return
  }
  Confirm('删除菜单，会将其子菜单一起删除，确定这样操作吗？').then(() => {
    delMenus()
  }).catch(() => {
    Msg({ kind: 'info', txt: "取消处理选中的数据！" })
  })
}
// delMenus 删除菜单实现，分离出来防止调用时异步报错
const delMenus = async () => {
  let menuIds = idList.value.join(',')
  loadShow.value = true
  try {
    const res = await delMenusApi({ menuIds })
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      await list()
      Msg({ kind: 'success', txt: '恭喜您，菜单信息删除成功！' })
    } else {
      Msg({ kind: 'error', txt: res.msg })
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

// setValue 为下拉框赋值
const setValue = (menu) => {
  // 调用排序接口
  sort(menu.selId, menu.selCode)
  menuForm.value.parentId = menu.selId
  menuForm.value.parentName = menu.selName
  menuForm.value.parentCode = menu.selCode
}

// sort 菜单排序
const sort = async (parentId, menuCode) => {
  const res = await sortMenuApi({ parentId })
  if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
    menuForm.value.sort = res.data
    // 为菜单自动编码
    menuForm.value.menuCode = menuCode.substring(0, menuCode.length-2) + '0' + res.data
  }
}

// chkShowed 单选框显示隐藏效果
const chkShowed = (idx) => {
  switch(idx) {
    case 1:
      menuForm.value.showed = 1
      break
    case 2:
      menuForm.value.showed = 2
      break
    default:
      menuForm.value.showed = 1
      break
  }
}
</script>

<template>
  <div class="menu-a">
    <div class="menu-b">
      <div class="menu-c">
        <div v-if="myAuth.saveAuth" class="btn-pi mr15" title="新增" @click="add"><i class="iconfont">&#xea2d;</i> 新增</div>
        <div v-if="myAuth.procAuth" class="btn-de mr15" title="删除" @click="deletes"><i class="iconfont">&#xea45;</i> 删除</div>
        <div class="btn-r mr15" title="刷新" @click="list"><i class="iconfont">&#xea8c;</i></div>
      </div>
      <div class="menu-d"><i class="iconfont">&#xeaaa;</i> 当前位置：工作台 > 系统管理 > 菜单管理</div>
    </div>
    <div v-if="hasData">
      <table>
        <tbody>
          <tr>
            <th style="width: 5%;"><span @click="checkAll()" title="全选"><i :class="['iconfont', allCheck ? 'chked' : 'chk']" v-html="allCheck ? '&#xea3a;' : '&#xea46;'" /></span></th>
            <th style="width: 7%;">图标</th>
            <th style="width: 23%;">名称</th>
            <th style="width: 15%;">编码</th>
            <th style="width: 20%;">地址</th>
            <th style="width: 10%;">排序</th>
            <th style="width: 10%;">显示</th>
            <th style="width: 10%;">操作</th>
          </tr>
          <tr v-for="(curMenu, index) in menuList" :key="curMenu.menuId" class="tr-style">
            <td class="txt-center"><span @click="checkCurId(index, curMenu.menuId)" title="选择"><i :class="['iconfont', checkList[index] ? 'chked' : 'chk']" v-html="checkList[index]  ? '&#xe685;' : '&#xe686;'" /></span></td>
            <td class="txt-center"><svg-icon :name="curMenu.icon" color="#333" /></td>
            <td><div :style="{'padding-left': curMenu.level*15+'px'}" class="tooltip" :data-title="curMenu.menuName">{{curMenu.menuName}}</div></td>
            <td class="txt-center">{{curMenu.menuCode}}</td>
            <td>{{curMenu.url}}</td>
            <td class="txt-center">{{curMenu.sort}}</td>
            <td class="txt-center"><span :class="[curMenu.showed===1 ? 'tag-s' : 'tag-e']">{{curMenu.showed===1 ? '显示' : '隐藏'}}</span></td>
            <td class="txt-center">
              <span v-if="myAuth.saveAuth" class="cl-warn" title="修改" @click="update(curMenu.menuId)"><i class="iconfont">&#xea48;</i> 修 改</span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <div v-else class="no-data">暂无内容</div>

    <!-- 新增、修改弹出层 -->
    <transition name="fade-mod" appear>
      <div v-if="showModal" class="modal-backdrop">
        <c-scrollbar>
          <div class="modal" style="width: 600px;">
            <div class="modal-header">
              <div class="header-left"><i class="iconfont">&#xea54;</i> 保存菜单信息</div>
              <div class="header-right" @click="closeModal()"><i class="iconfont fs22">&#xea7f;</i></div>
            </div>
            <div class="modal-body">
              <div>
                <div class="ipt-title"><span class="required">*</span>父级菜单</div>
                <tree-sel :tree-list="treeRef" :kind="1" :inboxed="false" :curName="menuForm.parentName!=='' ? menuForm.parentName+'['+menuForm.parentCode+']' : ''" pre-name="父级菜单" @setValue="setValue" />
              </div>
              <div>
                <div class="ipt-title"><span class="required">*</span>菜单排序</div>
                <div><input type="text" v-model="menuForm.sort" maxlength="11" placeholder="请输入菜单排序" class="ipt" /></div>
              </div>
              <div>
                <div class="ipt-title"><span class="required">*</span>菜单编码</div>
                <div><input type="text" v-model="menuForm.menuCode" maxlength="8" placeholder="请输入菜单编码" class="ipt" /></div>
              </div>
              <div>
                <div class="ipt-title"><span class="required">*</span>菜单名称</div>
                <div><input type="text" v-model="menuForm.menuName" maxlength="50" placeholder="请输入菜单名称" class="ipt" /></div>
              </div>
              <div>
                <div class="ipt-title">菜单图标</div>
                <div><input type="text" v-model="menuForm.icon" maxlength="30" placeholder="请输入菜单图标" class="ipt" /></div>
              </div>
              <div>
                <div class="ipt-title">菜单地址</div>
                <div><input type="text" v-model="menuForm.url" maxlength="60" placeholder="请输入跳转地址" class="ipt" /></div>
              </div>
              <div>
                <div class="ipt-title"><span class="required">*</span>是否显示</div>
                <div class="menu-e">
                  <div class="cur menu-f" @click="chkShowed(1)">
                    <i :class="['iconfont', 'mr5', menuForm.showed===1 ? 'chked' : 'chk']" v-html="menuForm.showed===1 ? '&#xe677;' : '&#xe678;'" />
                    <span>显示</span>
                  </div>
                  <div class="cur menu-f" @click="chkShowed(2)">
                    <i :class="['iconfont', 'mr5', menuForm.showed===2 ? 'chked' : 'chk']" v-html="menuForm.showed===2 ? '&#xe677;' : '&#xe678;'" />
                    <span>隐藏</span>
                  </div>
                </div>
              </div>
              <div>
                <div class="ipt-title">备注说明</div>
                <div><textarea v-model="menuForm.remarks" class="desc-txt"></textarea></div>
              </div>
            </div>
            <div class="modal-footer">
              <div class="btn-pi mr15" @click="save"><i class="iconfont">&#xea90;</i> 保存</div>
              <div class="btn-d" @click="closeModal"><i class="iconfont">&#xea4f;</i> 取消</div>
            </div>
          </div>
        </c-scrollbar>
      </div>
    </transition>
    <loader :loadShow="loadShow" />
  </div>
</template>

<style scoped>
.menu-a {padding: 10px;}
.menu-b {padding: 0 20px 10px 20px; display: flex; display: -webkit-flex;}
.menu-c {display: inline-flex; display: -webkit-inline-flex;}
.menu-d {flex-grow: 1; text-align: right; padding-top: 10px; color: #666;}
.menu-e {display: flex; display: -webkit-flex;}
.menu-f {width: 80px; margin: 10px;}
</style>